# -*- coding: UTF-8 -*-
import json
import logging
import socket
import struct
import thread
import time

import requests
from flask import Flask
from flask import request

import log_helper

g_sock = None
recive_auth_info = []
log_helper.init_logging('swj')
logger = logging.getLogger('swj')

app = Flask(__name__)


def int_to_hex_str(int_value):
    dest = hex(int_value)
    dest = str(dest).replace('0x', '')
    if len(dest) == 1:
        return "0" + dest
    return dest


def response_json(data, url):
    headers = {"Content-Type": "application/json"}
    post_data = json.dumps(data, ensure_ascii=False)
    logger.info("http_response:" + post_data)
    try_time = 0
    while try_time < 3:
        try:
            response = requests.post(url, data=post_data, headers=headers)
            if response.ok:
                logger.info("http_response_result:" + response.text)
                return
            logger.error("response status:" + str(response.status_code))
        except Exception as e:
            logger.error(e)
        time.sleep(0.1)
        try_time += 1


@app.route("/route/heart", methods=['POST', 'GET'])
def heart():
    request_text = request.get_data(as_text=True)
    if not request_text:
        return {"_status": 1, "_msg": "接受参数为空"}
    # logger.info(request_text)
    return {"msg": "ok", "type": "heart"}


@app.route("/route/report", methods=['POST', 'GET'])
def report():
    global recive_auth_info
    request_text = request.get_data(as_text=True)
    if not request_text:
        return {"_status": 1, "_msg": "接受参数为空"}
    logger.info(request_text)
    request_data = json.loads(request_text)
    if request_data['cmdType'] == 'auth':
        imsi = request_data['params']['imsi']
        plmn = request_data['params']['plmn']
        rand = request_data['params']['rand']
        auts = request_data['params']['auts']
        re_syn_flag = request_data['params']['reSynFlag']
        identifier = request_data['params']['identifier']
        recive_auth_info = []
        send_auth(str(imsi), str(plmn), str(re_syn_flag), auts, rand, identifier)
        count = 0
        while count < 40:
            if len(recive_auth_info) == 4:
                post_param = {
                    "cmdType": "auth",
                    "params": {
                        "identifier": identifier,
                        "kasme": recive_auth_info[0],
                        "rand": recive_auth_info[1],
                        "xres": recive_auth_info[2],
                        "autn": recive_auth_info[3]
                    }
                }
                response_json(post_param, "http://192.168.11.100:8666/receive")
                break
            time.sleep(0.2)
            count += 1
    if request_data['cmdType'] == 'authims':
        imsi = request_data['params']['imsi']
        plmn = request_data['params']['plmn']
        rand = request_data['params']['rand']
        auts = request_data['params']['auts']
        re_syn_flag = request_data['params']['reSynFlag']
        identifier = request_data['params']['identifier']
        recive_auth_info = []
        send_auth2(str(imsi), str(plmn), str(re_syn_flag), auts, rand, identifier)
        count = 0
        while count < 40:
            if len(recive_auth_info) == 5:
                post_param = {
                    "cmdType": "authims",
                    "params": {
                        "identifier": identifier,
                        "ck": recive_auth_info[0],
                        "ik": recive_auth_info[1],
                        "rand": recive_auth_info[2],
                        "xres": recive_auth_info[3],
                        "autn": recive_auth_info[4]
                    }
                }
                response_json(post_param, "http://192.168.11.100:8666/receive")
                break
            time.sleep(0.2)
            count += 1
    return {"msg": "ok", "type": "report"}


def listening():
    global g_sock, recive_auth_info
    g_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    g_sock.bind(('0.0.0.0', 10087))
    g_sock.settimeout(20)
    while True:
        try:
            data, addr = g_sock.recvfrom(16384)
            msg = data.strip()
            msg_len = len(msg)
            if msg_len == 0:
                continue
            unpack_data = struct.unpack(str(msg_len) + 'B', msg)
            if unpack_data[0] == 0 and len(unpack_data) == 77:
                recive_auth_info = parse_to_auth_info(unpack_data)
            if unpack_data[0] == 2 and len(unpack_data) == 77:
                recive_auth_info = parse_to_auth5_info(unpack_data)
        except Exception as e:
            logger.error(e)


def to_normal(int_value):
    dest = hex(int_value)
    dest = str(dest).replace('0x', '')
    if len(dest) == 1:
        dest = '0' + dest
    if dest[1] == 'f':
        dest = dest[0]
    if dest == 'ff':
        dest = ''
    return dest


def parse_to_auth_info(unpack_data):
    kasme = ''
    for i in range(1, 33):
        kasme += int_to_hex_str(unpack_data[i])
    rand = ''
    for i in range(33, 49):
        rand += int_to_hex_str(unpack_data[i])
    xres = ''
    for i in range(49, 57):
        xres += int_to_hex_str(unpack_data[i])
    autn = ''
    for i in range(57, 73):
        autn += int_to_hex_str(unpack_data[i])
    return [kasme, rand, xres, autn]


def parse_to_auth5_info(unpack_data):
    ck = ''
    for i in range(1, 17):
        ck += int_to_hex_str(unpack_data[i])
    ik = ''
    for i in range(17, 33):
        ik += int_to_hex_str(unpack_data[i])
    rand = ''
    for i in range(33, 49):
        rand += int_to_hex_str(unpack_data[i])
    xres = ''
    for i in range(49, 57):
        xres += int_to_hex_str(unpack_data[i])
    autn = ''
    for i in range(57, 73):
        autn += int_to_hex_str(unpack_data[i])
    return [ck, ik, rand, xres, autn]


def fix_arr_length(orgin_data, data_length):
    result_arr = [0] * data_length
    for idx, data in enumerate(orgin_data):
        result_arr[idx] = data
    return result_arr


def to_bcd(int_value):
    hex_value = hex(int_value)
    bcd = str(hex_value).replace('0x', '')
    if len(bcd) == 1:
        bcd = '0' + bcd
    dest = bcd[::-1]
    return dest


def str_to_bcd(str_val):
    ret_arr = []
    for i in range(0, len(str_val), 2):
        if i == (len(str_val) - 1):
            ret_arr.append('f' + str_val[i])
        else:
            ret_arr.append(str_val[i + 1] + str_val[i])
    return ''.join(ret_arr)


def hex_to_int(hex_val):
    ret_arr = []
    for i in range(0, len(hex_val), 2):
        if i != (len(hex_val) - 1):
            ret_arr.append(int(hex_val[i] + hex_val[i + 1], 16))
        else:
            ret_arr.append(int(hex_val[i], 16))
    return ret_arr


def send_auth(imsi='454001234560006', plmn='45402', re_syn_flag='00', auts='7f000060877fd51e7f00008f9f29',
              rand='611f7f000010887fd51e7f0000ffffff', identifier='01000000'):
    """

    :param imsi:
    :param plmn: 3
    :param auts:
    :param rand:
    :param identifier:
    :return:
    """
    r_response = [0]
    r_response.extend(hex_to_int(str_to_bcd(imsi)))
    plmn1 = str_to_bcd(plmn[0:3]) + str_to_bcd(plmn[3:])
    if len(plmn) <= 3:
        plmn1 += '0'
    r_response.extend(hex_to_int(plmn1))
    r_response.extend(hex_to_int(re_syn_flag))
    r_response.extend(hex_to_int(rand))
    r_response.extend(hex_to_int(auts))
    r_response.extend(hex_to_int(identifier))
    g_sock.sendto(struct.pack(str(len(r_response)) + 'B', *r_response), ('192.168.11.150', 10089))


def send_auth2(imsi='454001234560006', plmn='45402', re_syn_flag='00', auts='7f000060877fd51e7f00008f9f29',
               rand='611f7f000010887fd51e7f0000ffffff', identifier='01000000'):
    """

    :param imsi:
    :param plmn: 3
    :param auts:
    :param rand:
    :param identifier:
    :return:
    """
    r_response = [2]
    r_response.extend(hex_to_int(str_to_bcd(imsi)))
    plmn1 = str_to_bcd(plmn[0:3]) + str_to_bcd(plmn[3:])
    if len(plmn) <= 3:
        plmn1 += '0'
    r_response.extend(hex_to_int(plmn1))
    r_response.extend(hex_to_int(re_syn_flag))
    r_response.extend(hex_to_int(rand))
    r_response.extend(hex_to_int(auts))
    r_response.extend(hex_to_int(identifier))
    g_sock.sendto(struct.pack(str(len(r_response)) + 'B', *r_response), ('192.168.11.10', 10089))


def start():
    thread.start_new_thread(listening, ())
    time.sleep(2)
    # send_auth()
    # time.sleep(100000)


if __name__ == '__main__':
    # app.run(host='0.0.0.0', port=10020)
    # print str_to_bcd('00')
    start()
    app.run(host='0.0.0.0', port=10020)
